package com.nervenets.general.service;

import com.nervenets.general.entity.KeyValue;
import com.nervenets.general.hibernate.DomainObject;
import com.nervenets.general.model.SqlFunField;
import com.nervenets.general.web.params.FormParams;
import com.nervenets.general.web.params.Params;
import com.nervenets.general.web.params.QueryParams;
import com.nervenets.general.web.params.UpdateParams;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

public interface BaseService<T extends DomainObject> {

    <S extends BaseService<T>> T formSave(FormParams<T, S> params, HttpServletRequest request, HttpServletResponse response);

    T save(T var1, Params... params);

    List<T> saveAll(List<T> vars, Params... params);

    boolean existsById(long var1);

    Optional<T> findById(long var1);

    T findOne(long var1, String... nullMessages);

    T findOne(@NonNull QueryParams<T> params);

    <Temp> Temp findOne(long var1, Class<Temp> tempClass, String... nullMessages);

    List<T> findAllByIds(List<Long> ids);

    <Temp> List<Temp> findAllByIds(List<Long> ids, Class<Temp> tempClass);

    int updateById(long id, String field, Object value);

    int updateById(long id, KeyValue... keyValues);

    int update(@NonNull UpdateParams<T> updateParams);

    void deleteById(long var1);

    void deleteByIds(Iterable<Long> ids);

    void delete(T var1);

    void deleteAll(Iterable<? extends T> entities);

    int delete(@NonNull QueryParams<T> params);

    List<T> findAll();

    List<T> findAll(@NonNull QueryParams<T> params);

    List<T> findAll(@NonNull QueryParams<T> params, int size);

    List<T> findAll(@NonNull QueryParams<T> params, int size, Sort var2);

    List<T> findAll(@NonNull QueryParams<T> params, Sort var2);

    Page<T> findAll(@NonNull QueryParams<T> params, Pageable var2);

    List<T> findAll(Sort var2);

    Page<T> findAll(Pageable var2);

    List<HashMap<Object, Object>> findAll(String... fields);

    Page<HashMap<Object, Object>> findAll(Pageable pageable, String... fields);

    List<HashMap<Object, Object>> findAll(@NonNull QueryParams<T> params, String... fields);

    Page<HashMap<Object, Object>> findAll(@NonNull QueryParams<T> params, Pageable pageable, String... fields);

    <Temp> List<Temp> findAll(Class<Temp> tempClass);

    <Temp> List<Temp> findAll(@NonNull QueryParams<T> params, Class<Temp> tempClass);

    <Temp> List<Temp> findAll(@NonNull QueryParams<T> params, Class<Temp> tempClass, int size);

    <Temp> Page<Temp> findAll(@NonNull QueryParams<T> params, Class<Temp> tempClass, Pageable pageable);

    long count();

    long count(@NonNull QueryParams<T> params);

    List<HashMap<Object, Object>> count(@NonNull QueryParams<T> params, String... groupBys);

    Long countDistinct(@NonNull QueryParams<T> params, String field);

    List<HashMap<Object, Object>> countDistinct(@NonNull QueryParams<T> params, String field, String... groupBys);

    BigDecimal sum(String field, QueryParams<T> params);

    List<HashMap<Object, Object>> sum(String... fields);

    List<HashMap<Object, Object>> sum(@NonNull QueryParams<T> params, String... fields);

    List<HashMap<Object, Object>> sum(@NonNull QueryParams<T> params, String[] groupBys, String... fields);

    BigDecimal avg(String field, QueryParams<T> params);

    List<HashMap<Object, Object>> avg(String... fields);

    List<HashMap<Object, Object>> avg(@NonNull QueryParams<T> params, String... fields);

    List<HashMap<Object, Object>> avg(@NonNull QueryParams<T> params, String[] groupBys, String... fields);

    BigDecimal max(String field, QueryParams<T> params);

    List<HashMap<Object, Object>> max(String... fields);

    List<HashMap<Object, Object>> max(@NonNull QueryParams<T> params, String... fields);

    List<HashMap<Object, Object>> max(@NonNull QueryParams<T> params, String[] groupBys, String... fields);

    BigDecimal min(String field, QueryParams<T> params);

    List<HashMap<Object, Object>> min(String... fields);

    List<HashMap<Object, Object>> min(@NonNull QueryParams<T> params, String... fields);

    List<HashMap<Object, Object>> min(@NonNull QueryParams<T> params, String[] groupBys, String... fields);

    List<HashMap<Object, Object>> function(@NonNull QueryParams<T> params, String[] groupBys, SqlFunField[] fields);

    boolean hasUniqueKey(Long id, String field, Object value);

    boolean hasUniqueKey(Long id, @Nullable KeyValue... keyValues);

    boolean hasUniqueKey(Long id, @NonNull QueryParams<T> params);

    T findUniqueValue(Long id, String field, Object value);

    T findUniqueValue(Long id, @Nullable KeyValue... keyValues);

    T findUniqueValue(Long id, @NonNull QueryParams<T> params);
}
